/*
 * =====================================
 *   This is public Domain Code
 *   Contributed by: Gael Lafond
 *   24 March 2017
 * =====================================
 *
 * This is my attempt at creating a predictable
 * helix that can be created from any polygon.
 *
 * It works in a very similar fashion to rotate_extrude,
 * with a height parameter.
 *
 * The height of the final object is equal to the
 * height parameter + the height of the provided polygon.
 */

module helix_extrude(angle=360, height=100) {
	precision = $fn ? $fn : 24;

	// Thickness of polygon used to create an helix segment
	epsilon = 0.001;

	// Number of segments to create.
	//   I reversed ingenering rotate_extrude
	//   to provide a very similar behaviour.
	nbSegments = floor(abs(angle * precision / 360));

	module helix_segment() {
		// The segment is "render" (cached) to save (a lot of) CPU cycles.
		render() {
			// NOTE: hull() doesn't work on 2D polygon in a 3D space.
			//   The polygon needs to be extrude into a 3D shape
			//   before performing the hull() operation.
			//   To work around that problem, we create extremely
			//   thin shape (using linear_extrude) which represent
			//   our 2D polygon.
			hull() {
				rotate([90, 0, 0])
					linear_extrude(height=epsilon) children();

				translate([0, 0, height / nbSegments])
					rotate([90, 0, angle / nbSegments])
						linear_extrude(height=epsilon) children();
			}
		}
	}

	union() {
		for (a = [0:nbSegments-1])
			translate([0, 0, height / nbSegments * a])
				rotate([0, 0, angle / nbSegments * a])
					helix_segment() children();
	}
}

//MAIN SCRIPT************************************************************
//Variables
// Number of turns to generate
Nb_Turns = 8;
// Diameter of the helix profile (Do not touch for standard 3D filament (1.75mm)) 
Section_Diameter = 1.8;
// Diameter of the spring
Spring_Diameter = 25;
// Height of the spring
Height = 45;
// Faces resolution (Higher is smoother but increased compute time)
Resolution = 20;
rotate([180, 0, 0]) {
    difference() {
        union(){
            difference() {
                difference() {
                    union(){
                       
                        translate([0, 0,  -10]) cylinder (h = Height + 20, r=Spring_Diameter/2, $fn=100);
                    }
            helix_extrude(angle=360*Nb_Turns, height=Height, $fn=Resolution*2) {
            translate([Spring_Diameter/2, 0, 0]) {
                circle(r=Section_Diameter/2);
            }
            }
                };
                union(){
                    translate([0, 0,  -4]) rotate([0, 90, 0]) cylinder (h = Height + 20, r=Section_Diameter/2 + 0.25 ,center = true,  $fn=Resolution);
                    rotate([0, 90, 0]) cylinder (h = Spring_Diameter+1 , r=Section_Diameter/2 + 0.25 ,center = true,  $fn=Resolution);
                    translate([0, 0,  -2]) cube([Spring_Diameter, Section_Diameter + 0.25, 4], center = true);

                    
                     }
            };
                  
            translate([Spring_Diameter/2, 0, Height-0.5]) rotate([90, 0, 0]) cylinder (h = 5, r=Section_Diameter/2 + 1.5 ,center = true,  $fn=Resolution*4);
            
       };
       union(){
            translate([Spring_Diameter/2-0.25, 0, Height-0.25]) rotate([90, 0, 0]) cylinder (h = Spring_Diameter, r=Section_Diameter/2 + 0.35 ,center = true,  $fn=Resolution*2);
            translate([0, 0,  -15]) cylinder (h = Height + 30, r=Spring_Diameter/3, $fn=100);
           }
       
    };

       translate([Spring_Diameter/2-0.35,0,Height+Section_Diameter/2 + 1.5+0.75]) {
           rotate([-90, 0, 0]) {
               linear_extrude(5, center=true) {
                   polygon(
                       points = [
                          [0, 0],
                          [1.75,1.75],
                          [0, 1.75]
                                       ]
                                   );
                               }
           }
       }

}